home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
edit
/
elv18src.zip
/
redraw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-10
|
27KB
|
1,349 lines
/* redraw.c */
/* Author:
* Steve Kirkendall
* 14407 SW Teal Blvd. #C
* Beaverton, OR 97005
* kirkenda@cs.pdx.edu
*/
/* This file contains functions that draw text on the screen. The major entry
* points are:
* redrawrange() - called from modify.c to give hints about what parts
* of the screen need to be redrawn.
* redraw() - redraws the screen (or part of it) and positions
* the cursor where it belongs.
* idx2col() - converts a markidx() value to a logical column number.
*/
#include "config.h"
#include "vi.h"
#ifdef CRUNCH
# define NEAR LINES
#else
# define NEAR (*o_nearscroll&0xff)
#endif
/* This variable contains the line number that smartdrawtext() knows best */
static long smartlno;
/* This function remembers where changes were made, so that the screen can be
* redrawn in a more efficient manner.
*/
static long redrawafter; /* line# of first line that must be redrawn */
static long preredraw; /* line# of last line changed, before change */
static long postredraw; /* line# of last line changed, after change */
static int mustredraw; /* boolean: anything forcing a screen update? */
void redrawrange(after, pre, post)
long after; /* lower bound of redrawafter */
long pre; /* upper bound of preredraw */
long post; /* upper bound of postredraw */
{
if (after == redrawafter)
{
/* multiple insertions/deletions at the same place -- combine
* them
*/
preredraw -= (post - pre);
if (postredraw < post)
{
preredraw += (post - postredraw);
postredraw = post;
}
if (redrawafter > preredraw)
{
redrawafter = preredraw;
}
if (redrawafter < 1L)
{
redrawafter = 0L;
preredraw = postredraw = INFINITY;
}
}
else if (postredraw > 0L)
{
/* multiple changes in different places -- redraw everything
* after "after".
*/
postredraw = preredraw = INFINITY;
if (after < redrawafter)
redrawafter = after;
}
else
{
/* first change */
redrawafter = after;
preredraw = pre;
postredraw = post;
}
mustredraw = TRUE;
}
#ifndef NO_CHARATTR
/* see if a given line uses character attribute strings */
static int hasattr(lno, text)
long lno; /* the line# of the cursor */
REG char *text; /* the text of the line, from fetchline */
{
static long plno; /* previous line number */
static long chgs; /* previous value of changes counter */
static int panswer;/* previous answer */
char *scan;
/* if charattr is off, then the answer is "no, it doesn't" */
if (!*o_charattr)
{
chgs = 0; /* <- forces us to check if charattr is later set */
return FALSE;
}
/* if we already know the answer, return it... */
if (lno == plno && chgs == changes)
{
return panswer;
}
/* get the line & look for "\fX" */
if (!text[0] || !text[1] || !text[2])
{
panswer = FALSE;
}
else
{
for (scan = text; scan[2] && !(scan[0] == '\\' && scan[1] == 'f'); scan++)
{
}
panswer = (scan[2] != '\0');
}
/* save the results */
plno = lno;
chgs = changes;
/* return the results */
return panswer;
}
#endif
#ifndef NO_VISIBLE
/* This function checks to make sure that the correct lines are shown in
* reverse-video. This is used to handle the "v" and "V" commands.
*/
static long vizlow, vizhigh; /* the starting and ending lines */
static int vizleft, vizright; /* starting & ending indicies */
static int vizchange; /* boolean: must use stupid drawtext? */
static void setviz(curs)
MARK curs;
{
long newlow, newhigh;
long extra = 0L;
/* for now, assume the worst... */
vizchange = TRUE;
/* set newlow & newhigh according to V_from and cursor */
if (!V_from)
{
/* no lines should have reverse-video */
if (vizlow)
{
redrawrange(vizlow, vizhigh + 1L, vizhigh + 1L);
vizlow = vizhigh = 0L;
}
else
{
vizchange = FALSE;
}
return;
}
/* figure out which lines *SHOULD* have hilites */
if (V_from < curs)
{
newlow = markline(V_from);
newhigh = markline(curs);
vizleft = markidx(V_from);
vizright = markidx(curs) + 1;
}
else
{
newlow = markline(curs);
newhigh = markline(V_from);
vizleft = markidx(curs);
vizright = markidx(V_from) + 1;
}
/* adjust for line-mode hiliting */
if (V_linemd)
{
vizleft = 0;
vizright = BLKSIZE - 1;
}
else
{
extra = 1L;
}
/* arrange for the necessary lines to be redrawn */
if (vizlow == 0L)
{
/* just starting to redraw */
redrawrange(newlow, newhigh, newhigh);
}
else
{
/* Were new lines added/removed at the front? */
if (newlow != vizlow)
{
if (newlow < vizlow)
redrawrange(newlow, vizlow + extra, vizlow + extra);
else
redrawrange(vizlow, newlow + extra, newlow + extra);
}
/* Were new lines added/removed at the back? */
if (newhigh != vizhigh)
{
if (newhigh < vizhigh)
redrawrange(newhigh + 1L - extra, vizhigh + 1L, vizhigh + 1L);
else
redrawrange(vizhigh + 1L - extra, newhigh, newhigh);
}
}
/* remember which lines will contain hilighted text now */
vizlow = newlow;
vizhigh = newhigh;
}
#endif /* !NO_VISIBLE */
/* This function converts a MARK to a column number. It doesn't automatically
* adjust for leftcol; that must be done by the calling function
*/
int idx2col(curs, text, inputting)
MARK curs; /* the line# & index# of the cursor */
REG char *text; /* the text of the line, from fetchline */
int inputting; /* boolean: called from input() ? */
{
static MARK pcursor;/* previous cursor, for possible shortcut */
static MARK pcol; /* column number for pcol */
static long chgs; /* previous value of changes counter */
REG int col; /* used to count column numbers */
REG int idx; /* used to count down the index */
REG int i;
/* for now, assume we have to start counting at the left edge */
col = 0;
idx = markidx(curs);
/* if the file hasn't changed & line number is the same & it has no
* embedded character attribute strings, can we do shortcuts?
*/
if (chgs == changes
&& !((curs ^ pcursor) & ~(BLKSIZE - 1))
#ifndef NO_CHARATTR
&& !hasattr(markline(curs), text)
#endif
)
{
/* no movement? */
if (curs == pcursor)
{
/* return the column of the char; for tabs, return its last column */
if (text[idx] == '\t' && !inputting && !*o_list)
{
return pcol + *o_tabstop - (pcol % *o_tabstop) - 1;
}
else
{
return pcol;
}
}
/* movement to right? */
if (curs > pcursor)
{
/* start counting from previous place */
col = pcol;
idx = markidx(curs) - markidx(pcursor);
text += markidx(pcursor);
}
}
/* count over to the char after the idx position */
while (idx > 0 && (i = *text)) /* yes, ASSIGNMENT! */
{
if (i == '\t' && !*o_list)
{
col += *o_tabstop;
col -= col % *o_tabstop;
}
else if (i >= '\0' && i < ' ' || i == '\177')
{
col += 2;
}
#ifndef NO_CHARATTR
else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
{
text += 2; /* plus one more at bottom of loop */
idx -= 2;
}
#endif
else
{
col++;
}
text++;
idx--;
}
/* save stuff to speed next call */
pcursor = curs;
pcol = col;
chgs = changes;
/* return the column of the char; for tabs, return its last column */
if (*text == '\t' && !inputting && !*o_list)
{
return col + *o_tabstop - (col % *o_tabstop) - 1;
}
else
{
return col;
}
}
/* This function is similar to idx2col except that it takes care of sideways
* scrolling - for the given line, at least.
*/
int mark2phys(m, text, inputting)
MARK m; /* a mark to convert */
char *text; /* the line that m refers to */
int inputting; /* boolean: caled from input() ? */
{
int i;
i = idx2col(m, text, inputting);
while (i < leftcol)
{
leftcol -= *o_sidescroll;
mustredraw = TRUE;
redrawrange(1L, INFINITY, INFINITY);
}
while (i > rightcol)
{
leftcol += *o_sidescroll;
mustredraw = TRUE;
redrawrange(1L, INFINITY, INFINITY);
}
physrow = markline(m) - topline;
physcol = i - leftcol;
if (*o_number)
physcol += 8;
return physcol;
}
/* This function draws a single line of text on the screen. The screen's
* cursor is assumed to be located at the leftmost column of the appropriate
* row.
*/
static void drawtext(text, lno, clr)
REG char *text; /* the text to draw */
long lno; /* the nu